
import os
import os.path
import sys
import urllib
import xml.dom.minidom
import datetime
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import threading
from PIL import Image
from Config 		import *
from Constants 		import *
from Debug 			import *
from URI			import * 
from WebService 	import *
from Artist 		import *
from Album 			import *
from Track 			import *
import time


__version__ = ' 0.1.0'

__all__ = [	'DEBUG', 'Debug', 'Config', 'URI', 'Artist', 'Album', 
			'Track', 'WebService', 'AutoTag', 'AutoTagGUI']


#####################################################################################################################################
# AutoTag class
class AutoTag:

	def __init__(self,uri=None, artist=None, release=None):
		self.uri = uri
		self.artist = artist
		self.album = release
		
		format = Config().format_folder_input()
		
		self.the_artist = None
		self.the_album = None
		self.artist_list = []
		self.album_list = None
		
		if self.uri is not None:
			folder = os.path.basename(self.uri.get_dir()).split(Config.SEP)
			self.artist = folder[format.split(Config.SEP).index(Config.ARTIST_STR)].strip()
			self.album = folder[format.split(Config.SEP).index(Config.ALBUM_STR)].strip()
		DEBUG('Artist : ' + str(self.artist))
		DEBUG('Release: ' + str(self.album))
		DEBUG('-'*80)

		self.gui = AutoTagGUI(self)
		

	def search_artist(self, name, id):
		xml_file = WebService.get_artist(name=name, id = id)
		document = xml.dom.minidom.parseString(xml_file.read().strip())
		
		
		self.artist_list = []
		self.the_artist = None
		for node in document.getElementsByTagName('artist'):
			a = Artist(node)
			self.artist_list.append(a)
			self.the_artist = a.compare(self.the_artist)
		DEBUG(self.the_artist)
		return self.the_artist, self.artist_list
		
	def search_abum(self):
		xml_file = WebService.get_albums(self.the_artist)
		document = xml.dom.minidom.parseString(xml_file.read().strip())
		
		self.album_list = []
		self.the_album = None
		for node in document.getElementsByTagName('release'):
			l = Album(node, artist=self.the_artist)
			self.album_list.append(l)
			self.the_album = l.compare(self.the_album, self.album)
		DEBUG(self.the_album)
		return self.the_album, self.album_list
	
	def search_tracks(self):
		xml_file = WebService.get_tracks(self.the_album)
		document = xml.dom.minidom.parseString(xml_file.read().strip())
		
		self.track_list = []
		for node in document.getElementsByTagName('track'):
			t = Track(node)
			self.track_list.append(t)
		return self.track_list


	@staticmethod
	def get_files(uri):
		folder = uri.get_dir()
		files = []
		for file in os.listdir(folder):
			if file[-4:].upper() == '.MP3':
				files.append(file)
		return files
				
	def get_album_info(self):
		DEBUG(str(self.the_artist))
		DEBUG(str(self.the_album))

		artist = self.artist
		album = self.album
		
		xml_file = WebService.get_album_info(artist,album)
		document = xml.dom.minidom.parseString(xml_file.read().strip())
		url_cover = Album.get_cover(document)
		if self.the_album is not None:
			self.the_album.set_album_cover(url_cover)
		return url_cover
		
	def get_image_cover(self):
		url_cover = self.get_album_info()
		imgData = WebService.open(url_cover)
		return imgData
		
	def show_image_cover(self):
		imgData = self.get_image_cover()
		data = imgData.read()
		fd, name = tempfile.mkstemp()
		fp = open(name, 'wb')
		fp.write(data)
		fp.close()
		im = Image.open(name)
		im.show()
		os.remove(name)



class AutoTagGUI:
	def __init__(self, autotag):
		self.autotag = autotag
		self.show_interface()
		gtk.main()
	
	def key_press_event(self, widget, data=None):
		keyname = gtk.gdk.keyval_name(data.keyval)
		if keyname == 'Escape':
			self.destroy(widget,data)
			
	def set_label_bold(self, label=None, text=None):
		if text is None:
			text = label.get_text()
		label = gtk.Label()
		label.set_use_markup(True)
		label.set_markup('<b>' + text + '</b>')
		return label
		
			
	def show_interface(self):
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.resize(640, 480)
		self.window.set_border_width(10)
		self.window.set_border_width(5)
		self.window.connect('delete_event',self.delete_event)
		self.window.connect('key_press_event',self.key_press_event)

		self.handler_destroy = self.window.connect('destroy',self.destroy)
		self.window.set_title('AutoTag')
		self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
		self.window.set_resizable(not False)
		
		self.window.add(self.create_main_box())
		
		DEBUG('...showing PyGTK interface')
		self.search_artist.set_sensitive(True)
		self.window.show_all()

	def create_main_box(self):
		table = gtk.Table(1,5,False)
		table.attach(self.create_box_top(), 0, 1, 0, 1,xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=0, ypadding=0)
		table.attach(gtk.HSeparator(), 0, 1, 1, 2, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=7, ypadding=7)
		table.attach(self.create_box_middle(), 0, 1, 2, 3)
		table.attach(self.create_button_box(), 0, 1, 3, 4, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=0, ypadding=0) 
		table.attach(self.create_box_down(), 0, 1, 4, 5, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=0, ypadding=0)
		return table
		
	def get_file(self, url, name):
		filename = TEMP_FOLDER + os.sep+ name
		data = urllib.FancyURLopener().open(url)
		fp = open(filename, 'wb')
		fp.write(data.read())
		fp.close()
		return filename

	def create_box_top(self):
		table = gtk.Table(1,2, False)
		table.attach(self.create_image_panel(), 0, 1, 0, 1,xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		table.attach(self.create_info_panel(), 1, 2, 0, 1,xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0) 
		return table 
	
	
	def create_image_panel(self):
		frame = gtk.Frame()
		frame.set_label_widget(self.set_label_bold(text=' Album Image: '))
		img = gtk.Image()
		try:
			filename = self.get_file(COVER_BOX, 'box')
		except:
			filename = 'box.png'
		pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
		img.set_from_pixbuf(pixbuf)
		event = gtk.EventBox()
		event.set_border_width(5)
		event.add(img)
		
		self.img = img
		event.connect('button-press-event', self.click_cover_image)
		event.set_tooltip_text('Double clic to search the album cover')
		self.last_cover_search = (None, None)
		frame.add(event)
		return frame
	
	def click_cover_image(self, widget , data = None):
		if data.type == gtk.gdk._2BUTTON_PRESS and data.button == 1:
			if self.last_cover_search[0] == self.autotag.artist and self.last_cover_search[1] == self.autotag.album : return
			self.get_cover_and_show()
			self.save_cover.set_sensitive(True)
#			thread = threading.Thread(target=self.get_cover_and_show, args=())
#			thread.start()
			
			
	def get_cover_and_show(self):
		gtk.gdk.threads_enter()
		self.push_status('Searching cover...')
		self.autotag.artist = self.entry_artist.get_text()
		self.autotag.album = self.entry_album.get_text()
		
		self.last_cover_search = (self.autotag.artist, self.autotag.album)
		DEBUG('Searching cover for '+ self.autotag.artist + ' - ' + self.autotag.album)
		
		data = None
#		try:
		data = self.autotag.get_image_cover().read()
#		except:
#			data = open('img.png','r').read()

		fd, name = tempfile.mkstemp()
		fp = open(name, 'wb')
		fp.write(data)
		fp.close()
		cover = gtk.gdk.pixbuf_new_from_file(name)
		os.remove(name)
		
		scale = 174
		cover = cover.scale_simple(scale,scale,gtk.gdk.INTERP_BILINEAR)
		self.cover_pixbuf = cover
		img = self.img.get_pixbuf()
		
		x_off = 15
		y_off = 5
		cover.composite(img, x_off, y_off, cover.props.width, cover.props.height, x_off, y_off, 1.0, 1.0, gtk.gdk.INTERP_BILINEAR, 255)
		self.img.set_from_pixbuf(img)
		self.pop_status()
		gtk.gdk.threads_leave()

		
	
	def create_info_panel(self):
		table = gtk.Table(1,3,False)
		table.attach(self.create_request_panel(), 0, 1, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		table.attach(self.create_result_panel(), 0, 1, 1, 2 , xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		table.attach(self.create_folder_panel(), 0, 1, 2, 3 , xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		return table
	
	def create_request_panel(self):
		frame = gtk.Frame('')
		table = gtk.Table(2, 2, False)
		lbl = self.set_label_bold(text='Artist:')
		table.attach(lbl, 0, 1, 0, 1, xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		
		entry = gtk.Entry()
		entry.set_text(str(self.autotag.artist))
		table.attach(entry, 1, 2, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		self.entry_artist = entry
		
		lbl = self.set_label_bold(text='Album: ')
		table.attach(lbl, 0, 1, 1, 2, xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		
		entry = gtk.Entry()
		entry.set_text(str(self.autotag.album))
		table.attach(entry, 1, 2, 1, 2, xoptions=gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		self.entry_album = entry
		
		frame.add(table)
		return frame
	
	def create_result_panel(self):
		frame = gtk.Frame()
		frame.set_label_widget(self.set_label_bold(text=' Search: '))
		table = gtk.Table(2, 2, False)
		
		cell = gtk.CellRendererText()
		combo = gtk.ComboBox(model=gtk.ListStore(str))
		table.attach(combo, 0, 1, 0, 1,xoptions=gtk.EXPAND | gtk.FILL, yoptions=0, xpadding=0, ypadding=0)
		combo.pack_start(cell)
		combo.add_attribute(cell, 'text', 0)
		combo.set_sensitive(False)
		combo.connect('changed',self.update_artist)
		self.combo_artist = combo
		
		button = gtk.Button(stock='gtk-find')
		table.attach(button, 1, 2, 0, 1, xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		button.set_sensitive(False)
		button.connect('clicked',self.search_artist)
		self.search_artist = button
		
		cell = gtk.CellRendererText()
		combo = gtk.ComboBox(model=gtk.ListStore(str))
		table.attach(combo, 0, 1, 1, 2, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0, xpadding=0, ypadding=0)
		combo.pack_start(cell)
		combo.add_attribute(cell, 'text', 0)
		combo.set_sensitive(False)
		combo.connect('changed',self.update_album)
		self.combo_album = combo
		
		button = gtk.Button(stock='gtk-find')
		table.attach(button, 1, 2, 1, 2, xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		button.set_sensitive(False)
		button.connect('clicked',self.search_album)
		self.search_album = button
		
		frame.add(table)
		return frame
	
	def create_folder_panel(self):
		frame = gtk.Frame()
		frame.set_label_widget(self.set_label_bold(text='File folder:'))
		table = gtk.Table(1 , 2, False)
		
		entry = gtk.Entry()
		entry.set_text(self.autotag.uri.dir)
		entry.set_editable(False)
		table.attach(entry, 0, 1, 0, 1, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0, xpadding=0, ypadding=0)
		
		button = gtk.Button(label='Save cover')
		table.attach(button, 1, 2, 0, 1, xoptions=0, yoptions=0, xpadding=gtk.EXPAND|gtk.FILL, ypadding=0)
		button.connect('clicked', self.save_cover)
		button.set_sensitive(False)
		self.save_cover = button
		
		frame.add(table)
		return frame
	
	def save_cover(self, widget, data=None):
		DEBUG('Save cover')
		file = os.environ['HOME'] + os.sep + Config.get_cover_name()
		self.cover_pixbuf.save(file, 'jpeg', {'quality':'100'})
	
	
	def add_item_to_track_list(self, track_num, filename, new_filename, toggled=True):
			gtk.gdk.threads_enter()
			self.list_model.append(None,(int(track_num), filename, new_filename, toggled))
			gtk.gdk.threads_leave()
	
	def create_box_middle(self):
		frame = gtk.Frame()
		frame.set_label_widget(self.set_label_bold(text='Files &amp; Tracks:'))
		
		tree_store = gtk.TreeStore(int, str, str, bool)
		self.tree_store = tree_store
		
		self.list_model = tree_store
		view = gtk.TreeView(tree_store)
		self.tree_view = view
		
		renderer = gtk.CellRendererText()
		renderer.set_property('editable', True)
		renderer.set_property('xalign',0.50)
		column = gtk.TreeViewColumn('Track', renderer, text=0)
		view.append_column(column)
				
		renderer = gtk.CellRendererText()
		renderer.set_property('editable', False)
		
		column = gtk.TreeViewColumn('Name', renderer, text=1)
		column.set_property('resizable', False)
		column.set_property('expand',True)
		view.append_column(column)
		
		renderer = gtk.CellRendererText()
		renderer.set_property('editable', True)
		
		column = gtk.TreeViewColumn('New Name', renderer, text=2)
		column.set_property('resizable', False)
		column.set_property('expand',True)
		view.append_column(column)

		renderer = gtk.CellRendererToggle()
		renderer.set_property('activatable', True)
		renderer.set_property('xalign',0.50)
		renderer.connect('toggled', self.toggle_me, tree_store)
		
		column = gtk.TreeViewColumn('Update', renderer)
		column.set_property('resizable', False)
		column.add_attribute(renderer, 'active', 3)
		column.set_alignment(1.0)
		column.set_max_width(130)
		
		view.append_column(column)
		
		frame.add(view)

		return frame
	
	def toggle_me(self, cell, path, model):
		model[path][3] = not model[path][3]
		
	def create_button_box(self):
		buttonBox = gtk.HButtonBox()
		
		button = gtk.Button(stock=gtk.STOCK_FIND)
		button.set_sensitive(False)
		button.connect('clicked',self.fill_track_list)
		buttonBox.add(button)
		self.search_track = button
		
		button = gtk.Button(stock=gtk.STOCK_SAVE)
		button.set_sensitive(False)
		buttonBox.add(button)
		
		button = gtk.Button(stock=gtk.STOCK_QUIT)
		button.connect('clicked', self.destroy)
		buttonBox.add(button)
		
		return buttonBox
	
	def create_box_down(self):
		status = gtk.Statusbar()
		status.expand = False
		status.fill = not False
		status.homogeneous = False
		self.status = status
		self.context_id = None 
		return self.status
	
	
	def search_artist(self, widget, data=None):
		t = threading.Thread(target=self.search_artist_thread)  
		t.start()
		
	
	def search_artist_thread(self):
		self.push_status('Searching artist...')
		name_artist = self.entry_artist.get_text()
	
		id_artist = None
		for artist in self.autotag.artist_list:
			if artist.display_name == name_artist:
				id_artist = artist.ID
				name_artist = None
				break
		
		if name_artist is not None and len(name_artist.strip())== 0 :
			msg = '\nWrite an artist name in the text box'
			self.show_message(gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
			return
		
		the_artist, list = self.autotag.search_artist(name_artist,id_artist)
		model = gtk.ListStore(str)
		
		if len(list) == 0 : return
		for artist in list:
			model.append([artist.display_name])
		self.combo_artist.set_model(model)
		self.combo_artist.set_active(list.index(the_artist))
		self.combo_artist.set_sensitive(True)
		self.search_album.set_sensitive(True)
		self.push_status(str(len(list)) + ' artists found')

		
	def search_album(self, widget, data=None):
		t = threading.Thread(target=self.search_album_thread)
		t.start()

	
	def search_album_thread(self):
		if self.entry_artist.get_text() != self.autotag.the_artist.display_name:
			msg = '\nThe Artist was changed.\nPlease research the artist first'
			self.show_message(gtk.MESSAGE_INFO, gtk.BUTTONS_OK, msg)
			return
		
		self.autotag.album = self.entry_album.get_text()
		the_album, list = self.autotag.search_abum()
		model = gtk.ListStore(str)
		
		if len(list) == 0 :	return
		for album in list:
			model.append([album.title])
		self.combo_album.set_model(model)
		self.combo_album.set_active(list.index(the_album))
		self.combo_album.set_sensitive(True)
		self.search_track.set_sensitive(True)

		
	def fill_track_list(self, widget, data=None):
		list = self.autotag.search_tracks()
		files = AutoTag.get_files(self.autotag.uri)
		
		tree_store = gtk.TreeStore(int, str, str, bool)
		self.tree_store = tree_store
		self.list_model = tree_store
		self.tree_view.set_model(tree_store)

		for track in list:
			track.info()
			track.match_file(files)
			self.add_item_to_track_list(track.number, track.file, track.get_new_filename(), True)
		
	def update_artist(self, widget, data=None):
		display_name = self.combo_artist.get_active_text()
		print display_name
		
		new_artist = None
		for artist in self.autotag.artist_list:
			if artist.display_name == display_name:
				new_artist = artist
		
		if new_artist is None:
			self.autotag.artist = display_name
			self.entry_artist.set_text(display_name)
		else:
			self.autotag.artist = new_artist.name
			self.entry_artist.set_text(new_artist.display_name)
		
		self.autotag.the_artist = new_artist
		
	def update_album(self, widget, data=None):
		new_album = self.combo_album.get_active_text()
		self.autotag.album = new_album
		for album in self.autotag.album_list:
			if album.title == new_album:
				self.autotag.the_album = album
		self.entry_album.set_text(new_album)

		

	def push_status(self, msg):
		if self.context_id is not None:
			self.pop_status()
		self.context_id = self.status.get_context_id(msg)
		self.status.push(self.context_id,msg)
	
	def pop_status(self):
		self.status.pop(self.context_id)

	def delete_event(self, widget, event, data=None):
		DEBUG('Delete event ocurred')
		return False
	
	def show_message(self, type, buttons, message):
		dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, type, buttons, message)
		dialog.run()
		dialog.destroy()

	def destroy(self, widget, data=None):
		gtk.main_quit()
		DEBUG('...close application')
		sys.exit(0)



if __name__=='__main__':
	uri = URI(sys.argv[1])
	a = AutoTag(uri=uri,artist='Radiohead',release='In Rainbows')

